package com.lagou.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.ZkClient;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;
import java.util.Objects;
import java.util.Properties;

/**
 * @author czq
 * @date 2020/8/27 1:04
 */
@Configuration
@MapperScan(basePackages = "com.lagou.dao")
public class DataSourceConfig {

    private static ZkClient zkClient;

    private SqlSessionFactory sqlSessionFactory;

    public DataSourceConfig() {
        zkClient = new ZkClient("127.0.0.1:2181");
    }

    /**
     * 创建数据源
     */
    @Bean
    public DataSource getDataSource() throws Exception {
        Properties properties = new Properties();
        properties.put("driverClassName", zkClient.readData("/dataSource/driver"));
        properties.put("url", zkClient.readData("/dataSource/url"));
        properties.put("username", zkClient.readData("/dataSource/username"));
        properties.put("password", zkClient.readData("/dataSource/password"));

        return DruidDataSourceFactory.createDataSource(properties);
    }

    /**
     * 根据数据源创建SqlSessionFactory
     */
    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        sqlSessionFactory = sqlSessionFactoryBean.getObject();
        addDataBaseConfigurationListener();
        return sqlSessionFactory;
    }

    private void addDataBaseConfigurationListener() {
        // 监听节点变化（简化操作只对 url 进行监听）
        zkClient.subscribeDataChanges("/dataSource/url", new IZkDataListener() {
            @Override
            public void handleDataChange(String s, Object o) throws Exception {
                if (!Objects.isNull(sqlSessionFactory)) {
                    DruidDataSource druidDataSource = (DruidDataSource) sqlSessionFactory.getConfiguration().getEnvironment().getDataSource();
                    druidDataSource.close();
                    druidDataSource.restart();
                    druidDataSource.setUrl(zkClient.readData("/dataSource/url"));
                    druidDataSource.setUsername(zkClient.readData("/dataSource/username"));
                    druidDataSource.setPassword(zkClient.readData("/dataSource/password"));
                    druidDataSource.setDriverClassName(zkClient.readData("/dataSource/driver"));
                }
            }

            @Override
            public void handleDataDeleted(String s) throws Exception {

            }
        });
    }
}
